package com.hundsun.yr.universal.library.view.banner;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.animation.Interpolator;

/**
 * @Title: LoopViewPager.java
 * @Description: ViewPager类可以无限滚动 当适配器为 FragmentPagerAdapter 或者 FragmentStatePagerAdapter适配器必须执行 seBoundaryCaching( true )
 * @date 2015-12-4 上午11:23:04
 * @author:hejun.shen
 * @email:shenhj15971@hundsun.com
 * @replace author:
 * @replace date:
 * @version V1.0
 */
public class LoopViewPager extends ViewPager {

	public static final int DEFAULT_INTERVAL = 5000;

	/** 默认滚动时间 **/
	private long interval = DEFAULT_INTERVAL;
	/** 是否停止自动滚动 **/
	private boolean stopScrollWhenTouch = true;
	/** 自动滚动动画 **/
	private double autoScrollFactor = 1.0;
	/** 滑动动画 **/
	private double swipeScrollFactor = 1.0;

	private static final boolean DEFAULT_BOUNDARY_CASHING = false;

	private OnPageChangeListener mOuterPageChangeListener;
	private static LoopPagerAdapterWrapper mAdapter;
	private boolean mBoundaryCaching = DEFAULT_BOUNDARY_CASHING;
	public static final int SCROLL_WHAT = 0;
	private Handler handler;
	private ViewPagerScroller scroller = null;

	private boolean isAutoScroll = false;

	private boolean isloop = true;

	/**
	 * 
	 * @param position
	 * @param count
	 * @return (position-1)%count
	 */
	public static int toRealPosition(int position, int count) {
		position = position - 1;
		if (position < 0) {
			position += count;
		} else {
			position = position % count;
		}
		return position;
	}

	/**
	 * 如果设置为真，边界视图（即第一和最后一个）将永远不会被销毁 防止滑动闪屏
	 * 
	 * @param flag
	 */
	public void setBoundaryCaching(boolean flag) {
		if (isloop) {
			mBoundaryCaching = flag;
			if (mAdapter != null) {
				mAdapter.setBoundaryCaching(flag);
			}
		}
	}

	@Override
	public void setAdapter(PagerAdapter adapter) {
		setAdapter(adapter, true);
	}

	public void setAdapter(PagerAdapter adapter, boolean isloop) {
		this.isloop = isloop;
		if (isloop) {
			mAdapter = new LoopPagerAdapterWrapper(adapter);
			mAdapter.setBoundaryCaching(mBoundaryCaching);
			super.setAdapter(mAdapter);
		} else {
			super.setAdapter(adapter);
		}
		setCurrentItem(0);
	}

	@Override
	public PagerAdapter getAdapter() {
		if (isloop) {
			return mAdapter != null ? mAdapter.getRealAdapter() : mAdapter;
		} else {
			return super.getAdapter();
		}
	}

	@Override
	public int getCurrentItem() {
		if (isloop) {
			return mAdapter != null ? mAdapter.toRealPosition(super.getCurrentItem()) : 0;
		} else {
			return super.getCurrentItem();
		}
	}

	public void setCurrentItem(int item, boolean smoothScroll) {
		int realItem;
		if (isloop) {
			realItem = mAdapter.toInnerPosition(item);
		} else {
			realItem = item;
		}
		super.setCurrentItem(realItem, smoothScroll);
	}

	@Override
	public void setCurrentItem(int item) {
		if (getCurrentItem() != item) {
			setCurrentItem(item, true);
		}
	}

	@Override
	public void setOnPageChangeListener(OnPageChangeListener listener) {
		mOuterPageChangeListener = listener;
	};

	public LoopViewPager(Context context) {
		super(context);
		init();
	}

	public LoopViewPager(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	private void init() {
		handler = new AutoHandler(this);
		setViewPagerScroller();
		super.addOnPageChangeListener(onPageChangeListener);
	}

	private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
		private float mPreviousOffset = -1;
		private float mPreviousPosition = -1;

		@Override
		public void onPageSelected(int position) {
			int realPosition;
			if (isloop) {
				realPosition = mAdapter.toRealPosition(position);
			} else {
				realPosition = position;
			}

			if (mPreviousPosition != realPosition) {
				mPreviousPosition = realPosition;
				if (mOuterPageChangeListener != null) {
					mOuterPageChangeListener.onPageSelected(realPosition);
				}
			}
		}

		@Override
		public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
			int realPosition = position;
			if (isloop) {
				if (mAdapter != null) {
					realPosition = mAdapter.toRealPosition(position);
					if (positionOffset == 0 && mPreviousOffset == 0 && (position == 0 || position == mAdapter.getCount() - 1)) {
						setCurrentItem(realPosition);
					}

				}
				mPreviousOffset = positionOffset;
				if (mOuterPageChangeListener != null) {
					if (realPosition != mAdapter.getRealCount() - 1 && isloop) {
						mOuterPageChangeListener.onPageScrolled(realPosition, positionOffset, positionOffsetPixels);
					} else {
						if (positionOffset > .5) {
							mOuterPageChangeListener.onPageScrolled(0, 0, 0);
						} else {
							mOuterPageChangeListener.onPageScrolled(realPosition, 0, 0);
						}
					}
				}
			} else {
				if (mOuterPageChangeListener != null) {
					mOuterPageChangeListener.onPageScrolled(realPosition, positionOffset, positionOffsetPixels);
				}
			}

		}
	

		@Override
		public void onPageScrollStateChanged(int state) {
			if (mAdapter != null && isloop) {
				int position = LoopViewPager.super.getCurrentItem();
				int realPosition = mAdapter.toRealPosition(position);
				if (state == ViewPager.SCROLL_STATE_IDLE && (position == 0 || position == mAdapter.getCount() - 1)) {
					setCurrentItem(realPosition, false);
				}
			}
			if (mOuterPageChangeListener != null) {
				mOuterPageChangeListener.onPageScrollStateChanged(state);
			}
		}
	};

	/**
	 * 
	 * @Title: LoopViewPager.java
	 * @Description: 自动轮播Handler
	 * @date 2015-12-4 上午9:55:06
	 * @author:hejun.shen
	 * @email:shenhj15971@hundsun.com
	 * @replace author:
	 * @replace date:
	 * @version V1.0
	 */
	private static class AutoHandler extends Handler {

		private final WeakReference<LoopViewPager> autoScrollViewPager;

		public AutoHandler(LoopViewPager autoScrollViewPager) {
			this.autoScrollViewPager = new WeakReference<LoopViewPager>(autoScrollViewPager);
		}

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);

			switch (msg.what) {
			case SCROLL_WHAT:
					
				if(mAdapter==null)return;
				if (mAdapter.getCount() > 3) {
					LoopViewPager pager = this.autoScrollViewPager.get();
					if (pager != null) {
						pager.scroller.setScrollDurationFactor(pager.autoScrollFactor);
						pager.scrollOnce();
						pager.scroller.setScrollDurationFactor(pager.swipeScrollFactor);
						pager.sendScrollMessage(pager.interval + pager.scroller.getDuration());
					}
				}
			default:
				break;
			}
		}
	}

	/**
	 * 设置自动轮播持续时间
	 */
	public void setAutoScrollDurationFactor(double scrollFactor) {
		autoScrollFactor = scrollFactor;
	}

	/**
	 * 开始自动轮播
	 */
	public void startAutoScroll() {
		isAutoScroll = true;
		sendScrollMessage((long) (interval + scroller.getDuration() / autoScrollFactor * swipeScrollFactor));
	}

	/**
	 * 设置滚动条改变ViewPager动画持续时间
	 */
	private void setViewPagerScroller() {
		try {
			Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
			scrollerField.setAccessible(true);
			Field interpolatorField = ViewPager.class.getDeclaredField("sInterpolator");
			interpolatorField.setAccessible(true);

			scroller = new ViewPagerScroller(getContext(), (Interpolator) interpolatorField.get(null));
			scrollerField.set(this, scroller);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 只能滚动一次
	 */
	public void scrollOnce() {

		int position = getCurrentItem();
		int realPosition = position;

		if (mAdapter != null && isloop) {
			if (position == mAdapter.getCount() - 1) {
				setCurrentItem(0);
			} else {
				setCurrentItem(realPosition + 1);
			}
		}
	}

	/**
	 * 开始自动轮播
	 * 
	 * @param delayTimeInMills
	 */
	public void startAutoScroll(int delayTimeInMills) {
		isAutoScroll = true;
		sendScrollMessage(delayTimeInMills);
	}

	/**
	 * 停止自动轮播
	 */
	public void stopAutoScroll() {
		isAutoScroll = false;
		handler.removeMessages(SCROLL_WHAT);
	}

	private void sendScrollMessage(long delayTimeInMills) {
		/** 删除handler之前，保持一个handler是在运行的 **/
		handler.removeMessages(SCROLL_WHAT);
		handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);

	}

	/**
	 * 获取自动轮播时间
	 * 
	 * @return the interval
	 */
	public long getInterval() {
		return interval;
	}

	/**
	 * 设置自动轮播时间
	 * 
	 * @param interval
	 */
	public void setInterval(long interval) {
		this.interval = interval;
	}

	private boolean isStopByTouch = false;

	/**
	 * 获取触摸轮播状态
	 * 
	 * @return the stopScrollWhenTouch
	 */
	public boolean isStopScrollWhenTouch() {
		return stopScrollWhenTouch;
	}

	/**
	 * 当触摸时是否停止轮播（默认true）
	 * 
	 * @param stopScrollWhenTouch
	 */
	public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) {
		this.stopScrollWhenTouch = stopScrollWhenTouch;
	}

	/**
	 * 当stopScrollWhenTouch为 true Down 停止轮播 UP 开始轮播
	 */
	@SuppressLint("ClickableViewAccessibility")
	@Override
	public boolean onTouchEvent(MotionEvent ev) {

		int action = MotionEventCompat.getActionMasked(ev);

		if (stopScrollWhenTouch) {
			if ((action == MotionEvent.ACTION_DOWN) && isAutoScroll) {
				isStopByTouch = true;
				stopAutoScroll();
			} else if (ev.getAction() == MotionEvent.ACTION_UP && isStopByTouch) {
				startAutoScroll();
			}
		}
		// TODO Auto-generated method stub
		return super.onTouchEvent(ev);
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		Log.e("banner: loop",super.dispatchTouchEvent(ev) + "");
		return super.dispatchTouchEvent(ev);
	}
}
